package org.stvd.controller;

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.util.OAuth2Utils;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.stvd.common.security.SecurityUserHolder;
import org.stvd.common.security.support.UserDetail;
import org.stvd.common.security.support.UserSessionInfo;
import org.stvd.common.utils.StringsUtil;
import org.stvd.core.util.StringUtil;
import org.stvd.service.oauth.OauthAccessTokenService;
import org.stvd.service.oauth.OauthClientDetailsService;

/**
 * @Title LogoutController
 * @Describtion 系统登出控制类
 * @author houzxØå
 * @date 2021年6月18日
 */
@Controller
public class OauthSignOutController {
    
    @Autowired
    private TokenStore tokenStore;
    @Autowired
    private SessionRegistry sessionRegistry;
    @Autowired
    private OauthClientDetailsService oauthClientDetailsService;
    @Autowired
    private OauthAccessTokenService oauthAccessTokenService;
    
    /**
     * 服务端登出请求，无回调
     * @param request
     * @param response
     * @param access_token
     */
    @RequestMapping(value = "signout", method = RequestMethod.GET)
    public void userLogoutNoReturn(HttpServletRequest request, HttpServletResponse response, @RequestParam Map<String, String> parameters) {
        String userId = SecurityUserHolder.getCurrentUserId();
        if (StringUtil.isEmpty(userId)) {
            OAuth2Authentication oAuth2Authentication = tokenStore.readAuthentication(parameters.get(OAuth2AccessToken.ACCESS_TOKEN));
            if(oAuth2Authentication != null) {
                UserDetail userDetail =  (UserDetail)oAuth2Authentication.getPrincipal();
                userId = userDetail.getUsername();
            }
        }
        if (StringsUtil.isNotEmpty(userId)) {
            //失效Oauth2令牌
            oauthAccessTokenService.deleteUserTokenByUserName(userId);
            //退出用户Oauth2服务端登录
            new SecurityContextLogoutHandler().logout(request, null, null);
            //删除用户其他登录端session
            deleteUserSession(userId);
        }
    }
    
    /**
     * 服务端登出，有回调
     * @param request
     * @param response
     * @param access_token
     * @return
     */
    @RequestMapping(value = "signoutforback", method = RequestMethod.GET)
    public String userLogoutForReturn(HttpServletRequest request, HttpServletResponse response, @RequestParam Map<String, String> parameters) {
        if(!parameters.containsKey(OAuth2Utils.CLIENT_ID) || !parameters.containsKey(OAuth2Utils.REDIRECT_URI) || !parameters.containsKey(OAuth2AccessToken.ACCESS_TOKEN)){
            return "redirect:/login?error=params_error&error_description=required params missing";
        }
        if(!oauthClientDetailsService.hasOauthClientId(parameters.get(OAuth2Utils.CLIENT_ID))) {
            return "redirect:/login??error=params_error&error_description=invalid params";
        }
        String userId = SecurityUserHolder.getCurrentUserId();
        if (StringUtil.isEmpty(userId)) {
            OAuth2Authentication oAuth2Authentication = tokenStore.readAuthentication(parameters.get(OAuth2AccessToken.ACCESS_TOKEN));
            if(oAuth2Authentication != null) {
                UserDetail userDetail =  (UserDetail)oAuth2Authentication.getPrincipal();
                userId = userDetail.getUsername();
            }
        }
        if (StringsUtil.isNotEmpty(userId)) {
            //失效Oauth2令牌
            oauthAccessTokenService.deleteUserTokenByUserName(userId);
            //退出用户Oauth2服务端登录
            new SecurityContextLogoutHandler().logout(request, null, null);
            //删除用户其他登录端session
            deleteUserSession(userId);
        }
        return "redirect:"+parameters.get(OAuth2Utils.REDIRECT_URI);
    }
    
    public void deleteUserSession(String userId){
        List<Object> loginObjs = sessionRegistry.getAllPrincipals();
        for(Object obj : loginObjs){
            if(obj instanceof UserDetail){
                UserDetail userTemp = (UserDetail) obj;
                //根据用户对象获取用户的session对象
                List<SessionInformation> sessionInformationList = sessionRegistry.getAllSessions(userTemp, false);
                for(SessionInformation sessionInfo : sessionInformationList){
                    UserSessionInfo queryUserSessionInfo = 
                        new UserSessionInfo(sessionInfo.getPrincipal(),sessionInfo.getSessionId(),sessionInfo.getLastRequest());
                    if(queryUserSessionInfo.getPrincipal().getUsername().equals(userId)){
                        queryUserSessionInfo.expireNow();
                        sessionInfo.expireNow();
                    }
                }
            }
        }
    }
}
